迴圈是程式設計中最為重要的一環,因為他可以根據我們的設定重複執行某一項事情。 Verilog 也不例外,他包含 while, for, repeat, forever 等四種迴圈。在撰寫計數器的測試檔案時,我們曾使用過 for 迴圈來幫助執行,今天我們要來完整介紹這個主題。
雖然概念相同,但是在使用之前,我們還是要先徹底了解他的運作規則。因為迴圈搭配不同的電路可以產生不同的結果,如:分別搭配 Blocking 和 Nonblocking 就可能產生不同的結果。
註:所有迴圈都要被放置在 initial block 或 always block 中
先來看看 while 迴圈的語法,概念就和軟體設計一樣。當符合條件 (condition == True) 時,就會執行,且會不斷執行直到條件不符合!
while ( <condition> ) begin
// statements
end
舉一個例子吧。
reg [3:0] cnt;
initial begin
cnt = 1;
while (cnt <= 10) begin
$display("cnt: %d", cnt);
cnt = cnt + 1;
end
end
要特別注意的是 reg 要宣告足夠的數量。如果上述的宣告為 reg cnt
,那麼 while 迴圈不可能被終止,因為 cnt 只有 0, 1 兩種數值,無法到達更大的數值。
For 迴圈的語法需要包含三個部分:初始條件、終止條件、變化。語法如下:
for (<init> ; <terminate> ; <changes>) begin
// statements
end
試試用 for 迴圈來改寫 while 迴圈吧!
reg [3:0] cnt;
initial begin
for (cnt = 1; cnt <= 10 ; cnt = cnt + 1) begin
$display("cnt: %d", cnt);
end
end
Repeat 的中文是「重複」。而這種迴圈的功能也很簡單明瞭,只需要指定迴圈執行次數即可。語法如下:
repeat( <cycle> ) begin
// statements
end
<cycle> 除了可以直接給數值,也可以透過變數給值。特別要注意的是如果 <cycle> 在過程中被更動數值,不會影響執行圈數,舉一個例子就可以了解了!
reg [3:0] cnt;
initial begin
cnt = 6;
repeat(cnt) begin
$display("cnt: %d", cnt);
cnt --;
end
end
雖然變數 cnt 不斷在改變,但是 repeat 執行的圈數始終不變,因為圈數的設定在開始後就不能再被更動了。
這種迴圈會不斷被執行,結束迴圈的唯一方式是終止程式。
Forever 最常用於產生時脈:
initial #50 $finish;
initial begin
clk = 0;
forever begin
#5 clk = ~clk;
$display("clk: %b", clk);
end
end
如果將兩個 initial 合併會發生什麼事?程式碼如下:
initial begin clk = 0; forever begin #5 clk = ~clk; $display("clk: %b", clk); end #50 $finish; end
這個程式不可能會停止,因為 $finish 要被執行前,要先把 forever loop 結束掉,但這是不可能的,因此我們要把他分成兩個程式區塊來進行。
迴圈的語法跟使用很簡單,難的點在於內部電路會怎麼被執行,這部分還是要依賴經驗的累積。